﻿using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Me.Practice.ElevatorEngine.Domain.Entity;

namespace Me.Practice.ElevatorEngine.Infrastructure
{
    public delegate void ElevatorMovedHandler(ElevatorController controller, int toFloor);

    public class ElevatorController
	{
		private volatile bool _interruptSignal;			
		private readonly ElevatorCycle _elevatorCycle;
        private ElevatorMovedHandler _moved;
		
		public ElevatorController(Elevator elevator)
		{
			ControlledElevator = elevator;
			_interruptSignal = false;
			
			ControlledElevator.CurrentFloorNumber = BuildingContext.Floors.Min().Number;
			_elevatorCycle = new ElevatorCycle(ControlledElevator.CurrentFloorNumber);
		}

        public void Move()
        {
            var floor = BuildingContext.Floors.Single(f => f.Number == ControlledElevator.CurrentFloorNumber);
            lock (this)
            {
                _moved(this, floor.Number);
            }
            ControlledElevator.CurrentFloorNumber = _elevatorCycle.NextFloor();

            EmulateMoving();
        }

        public void EmulateMoving()
		{
			Thread.Sleep(ControlledElevator.Timeout*1000);
		}
		
		public void ActivateElevator()
		{
			ControlledElevator.State = ElevatorState.Active;

            foreach (var floorController in BuildingContext.Controller.FloorControllers)
            {
                Moved += floorController.OnElevatorArrived;
            }
			
			while(!_interruptSignal)
				Move();
		}
		
		public void DeactivateElevator()
		{
			_interruptSignal = true;
			ControlledElevator.State = ElevatorState.Unpowered;
		}
		
		public Elevator ControlledElevator {get; private set;}	

        public event ElevatorMovedHandler Moved
        {
            add { if (value != null) _moved += value; }
            remove { if (value != null) _moved -= value; }
        }
	}
}
